<!DOCTYPE html>


<html lang="en">
  

    <head>
      <meta charset="utf-8" />
        
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1"
      />
      <title>Vue3 |  欢迎</title>
  <meta name="generator" content="hexo-theme-ayer">
      
      <link rel="shortcut icon" href="/favicon.ico" />
       
<link rel="stylesheet" href="/dist/main.css">

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css"
      />
      
<link rel="stylesheet" href="/css/custom.css">
 
      <script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>
       
 

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-bulma@5.0.1/bulma.min.css"
      />
      <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>

      <!-- mermaid -->
      
      <style>
        .swal2-styled.swal2-confirm {
          font-size: 1.6rem;
        }
      </style>
    <link rel="alternate" href="/atom.xml" title="欢迎" type="application/atom+xml">
</head>
  </html>
</html>


<body>
  <div id="app">
    
      
    <main class="content on">
      <section class="outer">
  <article
  id="post-Vue学习/Vue3"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  Vue3
</h1>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2022/01/19/Vue%E5%AD%A6%E4%B9%A0/Vue3/" class="article-date">
  <time datetime="2022-01-19T04:32:40.000Z" itemprop="datePublished">2022-01-19</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/Vue%E5%AD%A6%E4%B9%A0/">Vue学习</a>
  </div>
  
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> Word count:</span>
            <span class="post-count">5.1k</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> Reading time≈</span>
            <span class="post-count">23 min</span>
        </span>
    </span>
</div>
 
    </div>
      
    <div class="tocbot"></div>




  
    <div class="article-entry" itemprop="articleBody">
       
  <hr>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><hr>
<ol>
<li>通过脚手架Vite【vue的轻量级前端开发与构建工具】<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm init vite hello-vue3 -- --template vue</span><br></pre></td></tr></table></figure></li>
<li>通过vue-cli脚手架<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue create hello-vue3</span><br></pre></td></tr></table></figure></li>
<li>通过CDN引入<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=<span class="string">&quot;https://unpkg.com/vue@next&quot;</span>&gt;&lt;/script&gt;</span><br></pre></td></tr></table></figure></li>
</ol>
<hr>
<h3 id="新特性"><a href="#新特性" class="headerlink" title="新特性"></a>新特性</h3><hr>
<ul>
<li>组合式API</li>
<li>Teleport</li>
<li>片段</li>
<li>触发组件选项</li>
<li>来自<code>@vue/runtime-core</code>的<code>createRenderer</code>API,用于创建定义渲染器</li>
<li>单文件组合式API语法糖(<code>&lt;script setup&gt;</code>)</li>
<li>单文件组件状态驱动的CSS变量(<code>&lt;style&gt;</code>中的<code>v-bind</code>)</li>
<li>SFC <code>&lt;style scoped&gt;</code> 现在可以包含全局规划或只针对插槽内容的规则</li>
<li>Suspense（实验阶段）</li>
</ul>
<hr>
<h3 id="vue2到vue3中的变化"><a href="#vue2到vue3中的变化" class="headerlink" title="vue2到vue3中的变化"></a>vue2到vue3中的变化</h3><hr>
<h4 id="1-vue实例创建"><a href="#1-vue实例创建" class="headerlink" title="1. vue实例创建"></a>1. vue实例创建</h4><blockquote>
<p>在vue3中,没有组件构造器的概念</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//vue 2</span></span><br><span class="line"><span class="keyword">const</span> app = <span class="keyword">new</span> Vue(&#123;&#125;)</span><br><span class="line"><span class="comment">//vue 3</span></span><br><span class="line"><span class="keyword">const</span> app = createApp(App)</span><br></pre></td></tr></table></figure>
<h4 id="2-vue-router的使用"><a href="#2-vue-router的使用" class="headerlink" title="2. vue-router的使用"></a>2. vue-router的使用</h4><blockquote>
<p>需要配置vue-router4.0以上版本</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//必须在app.mount(&#x27;#app&#x27;);之前  </span></span><br><span class="line">app.use(router);  <span class="comment">// 使用的是router的实例，而不是构造器。</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//router.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; createRouter, createWebHashHistory &#125; <span class="keyword">from</span> <span class="string">&quot;vue-router&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Ref <span class="keyword">from</span> <span class="string">&#x27;./components/Ref.vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> routes = [&#123;</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&#x27;/ref&#x27;</span>,</span><br><span class="line">    <span class="attr">component</span>: Ref,</span><br><span class="line">&#125;];</span><br><span class="line"><span class="keyword">const</span> router = createRouter(&#123;</span><br><span class="line">    <span class="attr">history</span>: createWebHashHistory(),</span><br><span class="line">    routes,</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> router;</span><br></pre></td></tr></table></figure>

<h4 id="3-vuex的使用"><a href="#3-vuex的使用" class="headerlink" title="3. vuex的使用"></a>3. vuex的使用</h4><blockquote>
<p>需要配置vuex4.0以上版本</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 必须在app.mount(&#x27;#app&#x27;);之前</span></span><br><span class="line">app.use(store);</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; createStore &#125; <span class="keyword">from</span> <span class="string">&#x27;vuex&#x27;</span></span><br><span class="line"><span class="keyword">const</span> store = createStore(&#123;</span><br><span class="line">    <span class="attr">state</span>: &#123;</span><br><span class="line">        <span class="attr">message</span>: <span class="string">&quot;this is the message from vuex store&quot;</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> store;</span><br></pre></td></tr></table></figure>

<h4 id="4-v-for中的ref数组"><a href="#4-v-for中的ref数组" class="headerlink" title="4. v-for中的ref数组"></a>4. v-for中的ref数组</h4><blockquote>
<p>在vue2中，使用的<code>ref</code>attribute会用ref数组填充对应的<code>$ref</code>property。如果存在v-for嵌套的情况下，行为不明确且效率低</p>
</blockquote>
<blockquote>
<p>在vue3中不再自动创建<code>$ref</code>数组，需要从单个绑定获取多个ref，即将<code>ref</code>绑定到一个灵活的函数上</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&#x27;movie in movies&#x27;</span> </span></span><br><span class="line"><span class="tag">    <span class="attr">:key</span>=<span class="string">&#x27;movie.id&#x27;</span> </span></span><br><span class="line"><span class="tag">    <span class="attr">:ref</span>=<span class="string">&quot;setMovieVNs&quot;</span>&gt;</span></span><br><span class="line">    &#123;&#123; movie.name &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">name</span>: <span class="string">&quot;Ref&quot;</span>,</span><br><span class="line">  <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        <span class="attr">movies</span>:[&#123;</span><br><span class="line">            <span class="attr">id</span>:<span class="number">1</span>,</span><br><span class="line">            <span class="attr">name</span>:<span class="string">&quot;长津湖&quot;</span></span><br><span class="line">        &#125;,&#123;</span><br><span class="line">            <span class="attr">id</span>:<span class="number">2</span>,</span><br><span class="line">            <span class="attr">name</span>:<span class="string">&quot;铁道游击队&quot;</span></span><br><span class="line">        &#125;,&#123;</span><br><span class="line">            <span class="attr">id</span>:<span class="number">3</span>,</span><br><span class="line">            <span class="attr">name</span>:<span class="string">&quot;金刚川&quot;</span></span><br><span class="line">        &#125;,],</span><br><span class="line">        <span class="attr">movieNVs</span>:[],</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>:&#123;</span><br><span class="line">      <span class="function"><span class="title">setMovieVNs</span>(<span class="params">el</span>)</span>&#123;  <span class="comment">//需要手动将创建的虚拟节点，放入自创数组中。</span></span><br><span class="line">          <span class="keyword">if</span>(el)&#123;</span><br><span class="line">              <span class="built_in">this</span>.movieNVs.push(el);</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="function"><span class="title">showRef</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="built_in">this</span>.movieNVs);</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="5-异步组件"><a href="#5-异步组件" class="headerlink" title="5. 异步组件"></a>5. 异步组件</h4><p>概述：</p>
<ul>
<li>新的<code>defineAsyncComponent</code>,用于显式地定义异步组件</li>
<li><code>component</code>选项被重命名为<code>loader</code></li>
<li>Loader函数本身不再接收<code>resolve</code>和<code>reject</code>参数，且必须返回一个Promise </li>
</ul>
<blockquote>
<p>什么是异步组件?</p>
<blockquote>
<p>就是当有需要的时候，才会去进行加载，并且把结果缓存起来，供未来重载使用。</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p>一般配合路由使用（Vue Router 2.4.0+）。但路由的懒加载，不能使用<code>defineAsyncComponent</code></p>
</blockquote>
</blockquote>
<blockquote>
<p>vue2</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">const</span> AsyncHomeComponent = <span class="function">() =&gt;</span> <span class="keyword">import</span>(<span class="string">&#x27;./src/App.vue&#x27;</span>); <span class="comment">//简单写法</span></span><br><span class="line">  <span class="comment">// 高阶写法</span></span><br><span class="line">  <span class="keyword">const</span> AsyncHomeComponent = <span class="function">() =&gt;</span> &#123; </span><br><span class="line">    <span class="comment">// 需要加载的组件</span></span><br><span class="line">    <span class="attr">component</span>: <span class="keyword">import</span> (<span class="string">&#x27;./src/App.vue&#x27;</span>),</span><br><span class="line">    <span class="comment">// 正在加载的时候响应的组件</span></span><br><span class="line">    <span class="attr">loading</span>: LoadingComponent,</span><br><span class="line">    <span class="comment">// 加载失败的时候响应的组件</span></span><br><span class="line">    <span class="attr">error</span>: ErrorComponent,</span><br><span class="line">    <span class="comment">// 显示加载时组件的延时时间。（默认200ms）</span></span><br><span class="line">    <span class="attr">delay</span>: <span class="number">200</span>,</span><br><span class="line">    <span class="comment">// 超时时间，超时则显示error组件。（默认`Infinity`）</span></span><br><span class="line">    <span class="attr">timeout</span>: <span class="number">3000</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>vue3</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; defineAsyncComponent &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> AsyncHomeComponent = defineAsyncComponent(&#123;</span><br><span class="line">    <span class="comment">// 需要加载的组件</span></span><br><span class="line">    <span class="attr">laoder</span>: <span class="function">() =&gt;</span></span><br><span class="line">        <span class="keyword">import</span> (<span class="string">&#x27;./src/App.vue&#x27;</span>),</span><br><span class="line">    <span class="comment">// 正在加载的时候响应的组件</span></span><br><span class="line">    <span class="attr">loading</span>: LoadingComponent,</span><br><span class="line">    <span class="comment">// 加载失败的时候响应的组件</span></span><br><span class="line">    <span class="attr">error</span>: ErrorComponent,</span><br><span class="line">    <span class="comment">// 显示加载时组件的延时时间。（默认200ms）</span></span><br><span class="line">    <span class="attr">delay</span>: <span class="number">200</span>,</span><br><span class="line">    <span class="comment">// 超时时间，超时则显示error组件。（默认`Infinity`）</span></span><br><span class="line">    <span class="attr">timeout</span>: <span class="number">3000</span>,</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h4 id="6-attribute强制行为"><a href="#6-attribute强制行为" class="headerlink" title="6. attribute强制行为"></a>6. attribute强制行为</h4><blockquote>
<p>不影响绝大多数开发人员<br>attr=’false’并不会移除，需要attr=null 或 attr=undefined</p>
</blockquote>
<h4 id="7-attrs包含了class和style"><a href="#7-attrs包含了class和style" class="headerlink" title="7. $attrs包含了class和style"></a>7. $attrs包含了class和style</h4><blockquote>
<p>$attrs包含了所有attribute</p>
</blockquote>
<blockquote>
<p>vue2:原本<code>class</code>和<code>style</code>会被添加到根元素中。因为$attr不包括class和style。需要特殊处理</p>
</blockquote>
<blockquote>
<p>App.vue</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  <span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;<span class="name">router-link</span> <span class="attr">to</span>=<span class="string">&quot;/ref&quot;</span>&gt;</span>ref测试<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;<span class="name">attr-test</span> <span class="attr">id</span>=<span class="string">&quot;myAttr&quot;</span> <span class="attr">class</span>=<span class="string">&quot;myAttr&quot;</span> <span class="attr">style</span>=<span class="string">&quot;color:red&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="keyword">import</span> AttrTest <span class="keyword">from</span> <span class="string">&#x27;./components/AttrTest.vue&#x27;</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="attr">components</span>: &#123; AttrTest &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>AttrTest.vue</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  <span class="xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="xml">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>AttrTest<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-bind</span>=<span class="string">&quot;$attrs&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="xml"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="javascript"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="attr">name</span>: <span class="string">&quot;AttrTest&quot;</span>,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">     <span class="attr">inheritAttrs</span>: <span class="literal">false</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>vue2渲染结果：</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;myAttr&quot;</span> <span class="attr">style</span>=<span class="string">&quot;color: red;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>AttrTest<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">id</span>=<span class="string">&quot;myAttr&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>vue3渲染结果：</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>AttrTest<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">id</span>=<span class="string">&quot;myAttr&quot;</span> <span class="attr">class</span>=<span class="string">&quot;myAttr&quot;</span> <span class="attr">style</span>=<span class="string">&quot;color: red;&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="8-children移除"><a href="#8-children移除" class="headerlink" title="8. $children移除"></a>8. $children移除</h4><blockquote>
<p>建议使用<code>$refs</code>访问子组件</p>
</blockquote>
<h4 id="9-自定义指令"><a href="#9-自定义指令" class="headerlink" title="9. 自定义指令"></a>9. 自定义指令</h4><blockquote>
<p>进行了钩子命名的修改或者添加新的钩子</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-heighlight</span>=<span class="string">&quot;&#x27;yellow&#x27;&quot;</span>&gt;</span>高亮显示此文本<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>在vue2中，有如下钩子：</p>
</blockquote>
<ul>
<li>bind：指令绑定到元素后执行一次</li>
<li>inserted：元素插入父DOM后执行一次</li>
<li>update：元素更新，子元素未更新时，调用一次</li>
<li>componentUpdated：组件和子元素都被更新，调用一次</li>
<li>unbind：指令移除，调用一次<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Vue.directive(<span class="string">&#x27;highlight&#x27;</span>,&#123;</span><br><span class="line">  <span class="function"><span class="title">bind</span>(<span class="params">el,binding,vnode</span>)</span>&#123;</span><br><span class="line">    el.style.background = binding.value;</span><br><span class="line">    <span class="keyword">const</span> vm = vnode.context; <span class="comment">//vue2中获取实例的方法</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<blockquote>
<p>在vue3中，对钩子做了一定的修改:</p>
</blockquote>
</li>
<li>created：元素的attribute或事件监听器被应用之前调用</li>
<li>beforeMount：绑定到元素后执行一次【原来的bind】</li>
<li>mounted：元素插入父DOM后执行一次【原来的inserted】</li>
<li>beforeUpdate：元素本身被更新之前，调用一次</li>
<li>updated：元素更新，子元素未更新，调用一次</li>
<li>beforeUnmount：指令被移除前，调用一次</li>
<li>unmounted：指令移除，调用一次。【原来的unbind】<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Vue.directive(<span class="string">&#x27;highlight&#x27;</span>,&#123;</span><br><span class="line">  <span class="function"><span class="title">beforeMount</span>(<span class="params">el,binding,vnode</span>)</span>&#123;</span><br><span class="line">    el.style.background = binding.value;</span><br><span class="line">    <span class="keyword">const</span> vm = binding.instance; <span class="comment">//vue3中获取实例的方法</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="10-自主定义元素"><a href="#10-自主定义元素" class="headerlink" title="10. 自主定义元素"></a>10. 自主定义元素</h4><blockquote>
<p>使用如<code>Web Components API</code>定义的自主定义元素<code>&lt;new-button&gt;&lt;/new-button&gt;</code>，如何将其变为vue的自定义元素</p>
</blockquote>
<blockquote>
<p>vue2：</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Vue.config.ignoredElements = [<span class="string">&#x27;new-button&#x27;</span>]; <span class="comment">//声明外部自定义元素</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>vue3:</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = createApp(&#123;&#125;);</span><br><span class="line">app.config.compilerOptions.isCustomElement = <span class="function"><span class="params">tag</span> =&gt;</span> tag === <span class="string">&#x27;new-button&#x27;</span></span><br></pre></td></tr></table></figure>

<h4 id="11-定制内置元素【is的表达不同】"><a href="#11-定制内置元素【is的表达不同】" class="headerlink" title="11. 定制内置元素【is的表达不同】"></a>11. 定制内置元素【is的表达不同】</h4><p>对于<code>&lt;button is=&#39;new-button&#39;&gt;</code>而言</p>
<blockquote>
<p>vue2渲染后:</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">new-button</span>&gt;</span><span class="tag">&lt;/<span class="name">new-button</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>vue3:</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">document</span>.createElement(<span class="string">&#x27;button&#x27;</span>,&#123;<span class="attr">is</span>:<span class="string">&#x27;new-button&#x27;</span>&#125;); <span class="comment">//通过这个来渲染原生的button</span></span><br></pre></td></tr></table></figure>

<h4 id="12-特殊DOM内模板解析问题"><a href="#12-特殊DOM内模板解析问题" class="headerlink" title="12.特殊DOM内模板解析问题"></a>12.特殊DOM内模板解析问题</h4><blockquote>
<p>在ul、ol、table、select中，他们的子元素时有所限制的，只能是li、tr、option</p>
</blockquote>
<blockquote>
<p>在vue2中，使用is来绕过限制</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">tr</span> <span class="attr">is</span>=<span class="string">&quot;blog-post-row&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>在vue3中，由于is的行为变化，将元素解析为vue组件需要添加<code>vue:</code>前缀</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">tr</span> <span class="attr">is</span>=<span class="string">&quot;vue:blog-post-row&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="13-DATA选项"><a href="#13-DATA选项" class="headerlink" title="13.DATA选项"></a>13.DATA选项</h4><blockquote>
<p>vue3中，只接受<code>function</code>定义、返回<code>object</code>的<code>data</code>选项【换言之，不管子组件还是父组件，都需要用函数的形式定义选项data】</p>
</blockquote>
<h4 id="14-Mixin合并行为"><a href="#14-Mixin合并行为" class="headerlink" title="14.Mixin合并行为"></a>14.Mixin合并行为</h4><blockquote>
<p>个人感觉,不能使用Mixin,可读性太差了.</p>
</blockquote>
<blockquote>
<p>vue3中的Mixin以组件内数据为主,比如组件中说user对象具有id属性,而混合的对象中既有id也有name</p>
</blockquote>
<blockquote>
<p>对于vue2而言,会将二者融合,冲突数据以组件为主</p>
</blockquote>
<blockquote>
<p>对于vue3而言,不会融合,组件内有什么属性,就是什么.</p>
</blockquote>
<h4 id="15-新增emits选项"><a href="#15-新增emits选项" class="headerlink" title="15.新增emits选项"></a>15.新增emits选项</h4><blockquote>
<p>与<code>props</code>类似,<code>emits</code>可以用于声明组件可以触发那些事件,同时也具有验证器.</p>
</blockquote>
<blockquote>
<p>强烈推荐使用<code>emits</code>,因为<strong>移除了.native修饰符</strong>.任何未在<code>emits</code>中声明的事件监听器都会被算入到$attrs中,默认绑定在根节点上.</p>
</blockquote>
<h4 id="16-移除事件API"><a href="#16-移除事件API" class="headerlink" title="16.移除事件API"></a>16.移除事件API</h4><ul>
<li>$on</li>
<li>$off</li>
<li>$once<br>被移除</li>
</ul>
<h4 id="17-移除过滤器filters"><a href="#17-移除过滤器filters" class="headerlink" title="17.移除过滤器filters"></a>17.移除过滤器filters</h4><blockquote>
<p>建议采用computed 或 methods替代</p>
</blockquote>
<h4 id="18-新增片段"><a href="#18-新增片段" class="headerlink" title="18.新增片段"></a>18.新增片段</h4><blockquote>
<p>支持多根节点(片段)</p>
</blockquote>
<h4 id="19-函数创建组件"><a href="#19-函数创建组件" class="headerlink" title="19.函数创建组件"></a>19.函数创建组件</h4><blockquote>
<p>vue2</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="attr">functional</span>:<span class="literal">true</span>,</span><br><span class="line">  <span class="attr">props</span>:[<span class="string">&#x27;level&#x27;</span>],</span><br><span class="line">  <span class="function"><span class="title">render</span>(<span class="params">h,&#123;props,data,children&#125;</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> h(<span class="string">`h<span class="subst">$&#123;prorps.level&#125;</span>`</span>,data,children);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>或</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span> <span class="attr">functional</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">component</span></span></span><br><span class="line"><span class="tag">    <span class="attr">:is</span>=<span class="string">&quot;`h$&#123;props.level&#125;`&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">v-bind</span>=<span class="string">&quot;attrs&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">v-on</span>=<span class="string">&quot;listeners&quot;</span></span></span><br><span class="line"><span class="tag">  /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">props</span>: [<span class="string">&#x27;level&#x27;</span>]</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>vue3:</p>
</blockquote>
<ul>
<li><p>函数创建,h变成了全局变量,attrs\slots位于context中.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123;h&#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> Heading = <span class="function">(<span class="params">props,context</span>)=&gt;</span>&#123;</span><br><span class="line">  <span class="keyword">return</span> h(<span class="string">`h<span class="subst">$&#123;props.level&#125;</span>`</span>, context.attrs, context.slots);</span><br><span class="line">&#125;</span><br><span class="line">Heading.props = [<span class="string">&#x27;level&#x27;</span>];</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> Heading;</span><br></pre></td></tr></table></figure></li>
<li><p>单文件,不需要写functional;<code>$attrs</code>囊括了几乎所有attribute.包括<code>listeners</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">component</span></span></span><br><span class="line"><span class="tag">    <span class="attr">v-bind:is</span>=<span class="string">&quot;`h$&#123;$props.level&#125;`&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">v-bind</span>=<span class="string">&quot;$attrs&quot;</span></span></span><br><span class="line"><span class="tag">  /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="javascript">  <span class="attr">props</span>: [<span class="string">&#x27;level&#x27;</span>]</span></span><br><span class="line"><span class="javascript">&#125;</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="20-全局API"><a href="#20-全局API" class="headerlink" title="20.全局API"></a>20.全局API</h4><ul>
<li><p>Vue.config</p>
<blockquote>
<p>被<code>app.config</code>替代</p>
</blockquote>
</li>
<li><p>Vue.config.productionTip  &gt; 被移除</p>
<blockquote>
<p>大多数脚手架已经正确配置环境了,没有必要.</p>
</blockquote>
</li>
<li><p>Vue.config.ignoredElements      </p>
<blockquote>
<p>被<code>app.config.isCustomElement</code>替代</p>
</blockquote>
</li>
<li><p>Vue.component</p>
<blockquote>
<p>被<code>app.component</code>                   </p>
</blockquote>
</li>
<li><p>Vue.directive    </p>
<blockquote>
<p>被<code>app.directive</code>替代</p>
</blockquote>
</li>
<li><p>Vue.mixin                      </p>
<blockquote>
<p>被<code>app.mixin</code>替代,强烈推荐使用组合API代替mixin</p>
</blockquote>
</li>
<li><p>Vue.prototype    </p>
<blockquote>
<p>被<code>app.config.globalProperties</code>替代                    </p>
</blockquote>
</li>
<li><p>Vue.extend      &gt; 被移除        </p>
<blockquote>
<p>其实可以使用<code>defineComponent</code>或<code>defineAsyncComponent</code>来替代</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h4 id="21-全局API-Treeshaking-没看懂-先放着"><a href="#21-全局API-Treeshaking-没看懂-先放着" class="headerlink" title="21. 全局API Treeshaking(没看懂,先放着)"></a>21. 全局API Treeshaking(没看懂,先放着)</h4><h4 id="22-移除内联模版Attribute"><a href="#22-移除内联模版Attribute" class="headerlink" title="22. 移除内联模版Attribute"></a>22. 移除内联模版Attribute</h4><blockquote>
<p>vue2中</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">my-component</span> <span class="attr">inline-template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>它们将被编译为组件自己的模板，<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>而不是父级所包含的内容。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">my-component</span>&gt;</span> </span><br></pre></td></tr></table></figure>
<h4 id="23-key-Attribute"><a href="#23-key-Attribute" class="headerlink" title="23. key Attribute"></a>23. key Attribute</h4><blockquote>
<p>在vue2中,需要手动添加key,相当于给一个唯一标识.提高效率;</p>
</blockquote>
<blockquote>
<p>在vue3中,会自动添加key;key应该被设置在<code>&lt;template&gt;</code>中.</p>
</blockquote>
<h4 id="24-按键修饰符"><a href="#24-按键修饰符" class="headerlink" title="24. 按键修饰符"></a>24. 按键修饰符</h4><ul>
<li>不支持数字作为<code>v-on</code>的修饰符</li>
<li>不支持<code>config.keyCodes</code><blockquote>
<p>在vue3中,可以使用<strong>kebab-cased</strong>或者使用<strong>符号</strong>代替</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 回车键提交  --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">v-on:keyup.enter</span>=<span class="string">&#x27;submit&#x27;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 会同时匹配Q和q --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">v-on:keyup.q</span>=<span class="string">&#x27;quit&#x27;</span>&gt;</span> </span><br></pre></td></tr></table></figure>
<blockquote>
<p>关于符号问题，除了<code>&quot;</code>,<code>&#39;</code>,<code>/</code>,<code>=</code>,<code>&gt;</code>,和<code>.</code>之外，其他估计都可以直接用符号代替</p>
<blockquote>
<p>如<code>&lt;input v-on:keypress.,=&#39;commaPress&#39;&gt;</code></p>
</blockquote>
</blockquote>
</li>
</ul>
<h4 id="25-移除-listeners"><a href="#25-移除-listeners" class="headerlink" title="25. 移除$listeners"></a>25. 移除$listeners</h4><blockquote>
<p>$listenersr融合到$attrs中</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- vue2 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-bind</span>=<span class="string">&quot;$attrs&quot;</span> <span class="attr">v-on</span>=<span class="string">&quot;$listeners&quot;</span> /&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- vue3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-bind</span>=<span class="string">&quot;$attrs&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="26-挂载元素问题"><a href="#26-挂载元素问题" class="headerlink" title="26. 挂载元素问题"></a>26. 挂载元素问题</h4><blockquote>
<p>vue2中，被挂载元素会被替代</p>
</blockquote>
<blockquote>
<p>vue3中，挂载的模板会渲染到被挂载元素中，当作<code>innerHTML</code></p>
</blockquote>
<h4 id="27-移除propsData"><a href="#27-移除propsData" class="headerlink" title="27. 移除propsData"></a>27. 移除propsData</h4><blockquote>
<p>在vue2中，可以使用propsData给props传值</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Home = Vue.extend(&#123;</span><br><span class="line">  <span class="attr">props</span>:[<span class="string">&#x27;title&#x27;</span>],</span><br><span class="line">  <span class="function"><span class="title">render</span>(<span class="params">h</span>)</span>&#123;<span class="keyword">return</span> h(<span class="string">&#x27;div&#x27;</span>,title)&#125;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">new</span> Home(&#123;</span><br><span class="line">  <span class="attr">propsData</span>:&#123;</span><br><span class="line">    <span class="attr">title</span>:<span class="string">&#x27;NEW PASSAGE&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>在vue3中，可以使用<code>createApp</code>的第二个参数：</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; createApp , h &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>; </span><br><span class="line"><span class="keyword">const</span> Home = createApp(&#123;</span><br><span class="line">  <span class="attr">props</span>:[<span class="string">&#x27;title&#x27;</span>],</span><br><span class="line">  <span class="function"><span class="title">render</span>(<span class="params"></span>)</span>&#123;<span class="keyword">return</span> h(<span class="string">&#x27;div&#x27;</span>,title)&#125;</span><br><span class="line">&#125;,&#123;</span><br><span class="line">  <span class="attr">title</span>:<span class="string">&#x27;NEW PASSAGE&#x27;</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h4 id="18-prop的默认函数中不能访问this"><a href="#18-prop的默认函数中不能访问this" class="headerlink" title="18. prop的默认函数中不能访问this"></a>18. prop的默认函数中不能访问<code>this</code></h4><ul>
<li>组件接收到原始的prop将作为参数传递给默认函数</li>
<li>inject API可以在默认函数中使用<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; inject &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="attr">props</span>:&#123;</span><br><span class="line">    <span class="attr">theme</span>:&#123;</span><br><span class="line">      <span class="function"><span class="title">default</span>(<span class="params">props</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> inject(<span class="string">&#x27;theme&#x27;</span>,<span class="string">&#x27;default-theme&#x27;</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="19-Provide-Inject"><a href="#19-Provide-Inject" class="headerlink" title="19.Provide/Inject"></a>19.Provide/Inject</h4><blockquote>
<p><code>provide(name,value)</code>用于上层组件向下抛出变量</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 常适用于于组合API中</span></span><br><span class="line"><span class="keyword">import</span> &#123; provide &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    provide(<span class="string">&#x27;id&#x27;</span>,<span class="string">&#x27;flevena&#x27;</span>);  <span class="comment">//provide(抛出的名字，抛出的值)</span></span><br><span class="line">    provide(<span class="string">&#x27;score&#x27;</span>,&#123;</span><br><span class="line">      <span class="attr">math</span>:<span class="number">90</span>,</span><br><span class="line">      <span class="attr">english</span>:<span class="number">90</span>,</span><br><span class="line">      <span class="attr">average</span>:<span class="number">90</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p><code>inject(name[,default-value])</code>用于下层组件接收上层组件抛出的变量。以此实现了跨级组件的通信。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; inject &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> studentId = inject(<span class="string">&#x27;id&#x27;</span>,<span class="number">1</span>);    <span class="comment">// 接收抛出的id，并将其值设为1</span></span><br><span class="line">    <span class="keyword">const</span> studentScores = inject(<span class="string">&#x27;score&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      studentId,</span><br><span class="line">      studentScores</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>为了使得provide值和inject值之间具有响应性，可以在provide值时候，使用ref或reactive</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; provide , reactive , ref &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> location = ref(<span class="string">&#x27;North Pole&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> geolocation = reactive(&#123;</span><br><span class="line">      <span class="attr">longitude</span>:<span class="number">90</span>,</span><br><span class="line">      <span class="attr">latitude</span>:<span class="number">135</span></span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    provide(<span class="string">&#x27;location&#x27;</span>,location);</span><br><span class="line">    provide(<span class="string">&#x27;geolocation&#x27;</span>,geolocation);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>但是provide的值最好只能在提供者组件内部进行修改，其他子组件最好只能阅读。这样确保了数据的私密性。【java的setter、getter逻辑】</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; provide , reactive , ref , readonly &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>; </span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> location = ref(<span class="string">&#x27;North Pole&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> geolocation = reactive(&#123;</span><br><span class="line">      <span class="attr">longitude</span>:<span class="number">90</span>,</span><br><span class="line">      <span class="attr">latitude</span>:<span class="number">135</span></span><br><span class="line">    &#125;);</span><br><span class="line">   <span class="comment">// 提供修改的方法</span></span><br><span class="line">   <span class="keyword">const</span> updateLocation = <span class="function">(<span class="params">newLocation</span>) =&gt;</span>&#123;</span><br><span class="line">     location.value = newLocation;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">// 抛出变量和方法</span></span><br><span class="line">   provide(<span class="string">&#x27;location&#x27;</span>,readonly(location));</span><br><span class="line">   provide(<span class="string">&#x27;geolocation&#x27;</span>,readonly(geolocation));</span><br><span class="line">   provide(<span class="string">&#x27;updateLocation&#x27;</span>,updateLocation);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h4 id="20-渲染函数API"><a href="#20-渲染函数API" class="headerlink" title="20. 渲染函数API"></a>20. 渲染函数API</h4><blockquote>
<p>h变成了全局导入<code>import &#123; h &#125; from &#39;vue&#39;</code>,不再作为<code>render</code>的参数</p>
</blockquote>
<blockquote>
<p>由于<code>render</code>不再接收参数，所以一般<code>h</code>用于<code>setup()</code>内部。因为可以访问<strong>作用域内声明的响应式状态和函数以及<code>setup()</code>的参数</strong></p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; h, reactive &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params">props,&#123;solts,attrs,emit&#125;</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> state = reactive(&#123;</span><br><span class="line">      <span class="attr">count</span>:<span class="number">0</span>,</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">increment</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">      state.count++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//返回渲染函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function">()=&gt;</span>&#123;</span><br><span class="line">      h(<span class="string">&#x27;div&#x27;</span>,&#123;</span><br><span class="line">        <span class="attr">onClick</span>:increment</span><br><span class="line">      &#125;,state.count);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="21-注册组件"><a href="#21-注册组件" class="headerlink" title="21. 注册组件"></a>21. 注册组件</h4><blockquote>
<p>vue2中</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Vue.component(<span class="string">&#x27;new-button&#x27;</span>,&#123;&#125;);</span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="title">default</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">render</span>(<span class="params">h</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> h(<span class="string">&#x27;new-button&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>vue3中,由于VNode是上下文无关的，所以不能用字符串找到组件。需要<code>resolveComponent</code>方法解决</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; h, resolveComponent &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> newButton = resolveComponent(<span class="string">&#x27;new-button&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="function">()=&gt;</span>h(newButton);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="22-插槽统一"><a href="#22-插槽统一" class="headerlink" title="22. 插槽统一"></a>22. 插槽统一</h4><ul>
<li><code>this.$slots</code>,插槽作为函数公开.</li>
<li>移除<code>this.$scopedSlots</code><blockquote>
<p>在vue2中，</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在LayoutComponent中，创建两个作用域插槽，名为header和content。</span></span><br><span class="line">h(LayoutComponent,[</span><br><span class="line">  h(<span class="string">&#x27;div&#x27;</span>,&#123;<span class="attr">slot</span>:<span class="string">&#x27;header&#x27;</span>&#125;,<span class="built_in">this</span>.header),</span><br><span class="line">  h(<span class="string">&#x27;div&#x27;</span>,&#123;<span class="attr">slot</span>:<span class="string">&#x27;content&#x27;</span>&#125;,<span class="built_in">this</span>.content)</span><br><span class="line">])</span><br><span class="line"><span class="comment">// 引用作用域插槽：</span></span><br><span class="line"><span class="built_in">this</span>.$scopedSlots.header;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>vue3中</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">h(LayoutComponent,&#123;&#125;,&#123;</span><br><span class="line">  <span class="attr">header</span>:<span class="function">()=&gt;</span> h(<span class="string">&#x27;div&#x27;</span>,<span class="built_in">this</span>.hader),</span><br><span class="line">  <span class="attr">content</span>:<span class="function">()=&gt;</span> h(<span class="string">&#x27;div&#x27;</span>,<span class="built_in">this</span>.content)</span><br><span class="line">  <span class="comment">// vue3引用</span></span><br><span class="line">  <span class="built_in">this</span>.$slots.header();</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="23-过渡的class名更改了"><a href="#23-过渡的class名更改了" class="headerlink" title="23. 过渡的class名更改了"></a>23. 过渡的class名更改了</h4><p><code>v-enter</code> 改为 <code>v-enter-from</code><br><code>v-leave</code> 改为 <code>v-leave-from</code></p>
<blockquote>
<p>v-enter-active思路：从<code>v-enter-from</code> 到 <code>v-enter-to</code></p>
</blockquote>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.v-enter-from</span>,</span><br><span class="line"><span class="selector-class">.v-leave-to</span>&#123;</span><br><span class="line">  <span class="attribute">opacity</span>:<span class="number">0</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>v-leave-active思路：从<code>v-leave-from</code> 到 <code>v-leave-to</code></p>
</blockquote>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.v-leave-from</span>,</span><br><span class="line"><span class="selector-class">.v-enter-to</span>&#123;</span><br><span class="line">  <span class="attribute">opacity</span>:<span class="number">1</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="24-Transition"><a href="#24-Transition" class="headerlink" title="24. Transition"></a>24. Transition</h4><blockquote>
<p><code>&lt;transition&gt;</code>作为更根节点的组件，从外部切换时将不再触发过渡效果。</p>
</blockquote>
<h4 id="25-Transition-Group"><a href="#25-Transition-Group" class="headerlink" title="25. Transition Group"></a>25. Transition Group</h4><blockquote>
<p><code>&lt;transition-group&gt;</code> 不再默认渲染根元素，但仍然可以用<code>tag</code> attribute 创建根元素。</p>
</blockquote>
<h4 id="26-移除v-on-native"><a href="#26-移除v-on-native" class="headerlink" title="26. 移除v-on.native"></a>26. 移除v-on.native</h4><blockquote>
<p>可以使用**新增选项<code>emits</code>**定义允许被触发的事件</p>
</blockquote>
<h4 id="27-v-if和v-for的优先级问题"><a href="#27-v-if和v-for的优先级问题" class="headerlink" title="27. v-if和v-for的优先级问题"></a>27. <code>v-if</code>和<code>v-for</code>的优先级问题</h4><blockquote>
<p>vue2中，<code>v-for</code> 优先于 <code>v-if</code></p>
</blockquote>
<blockquote>
<p>vue3中，<code>v-if</code> 优先于 <code>v-for</code></p>
</blockquote>
<h4 id="28-v-bind合并行为"><a href="#28-v-bind合并行为" class="headerlink" title="28. v-bind合并行为"></a>28. <code>v-bind</code>合并行为</h4><blockquote>
<p>绑定顺序会影响渲染结果</p>
</blockquote>
<ul>
<li>vue2:<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 模板 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;red&#x27;</span> <span class="attr">v-bind</span>=<span class="string">&quot;&#123;id:&#x27;blue&#x27;&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 结果 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;red&#x27;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
<li>vue3:具有顺序的，后面会覆盖前面<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 模板 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;red&#x27;</span> <span class="attr">v-bind</span>=<span class="string">&quot;&#123;id:&#x27;blue&#x27;&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 结果 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;blue&#x27;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="29-hook-改为了-vnode"><a href="#29-hook-改为了-vnode" class="headerlink" title="29. hook: 改为了 vnode-"></a>29. hook: 改为了 vnode-</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- vue2 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">child-component</span> @<span class="attr">hook:updated</span>=<span class="string">&#x27;onUpdated&#x27;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- vue3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">child-component</span> @<span class="attr">vnode-updated</span>=<span class="string">&#x27;onUpdated&#x27;</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="30-侦听数组"><a href="#30-侦听数组" class="headerlink" title="30. 侦听数组"></a>30. 侦听数组</h4><blockquote>
<p>侦听数组的时候，只有数组<strong>被替代</strong>才会触发回调函数。</p>
</blockquote>
<blockquote>
<p>在vue3中，添加<code>deep:true</code>选项，数组<strong>改变</strong>就会触发回调函数</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">  watch: &#123;</span><br><span class="line">  <span class="attr">bookList</span>: &#123;</span><br><span class="line">    <span class="function"><span class="title">handler</span>(<span class="params">val, oldVal</span>)</span> &#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">&#x27;book list changed&#x27;</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">deep</span>: <span class="literal">true</span></span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Composition-API"><a href="#Composition-API" class="headerlink" title="Composition API"></a>Composition API</h3><h4 id="特点："><a href="#特点：" class="headerlink" title="特点："></a>特点：</h4><ol>
<li>Composition API是基于函数的，可以有效地组织和编写可重用代码（可以通过<code>provide</code> <code>inject</code> 共享变量、函数）</li>
<li>通过将共享逻辑分离为功能来提高代码的可读性</li>
<li>实现代码分离</li>
<li>在Vue中更好地使用TypeScript</li>
</ol>
<h4 id="setup-选项实现组合式API；组件创建前，props被解析后，setup就会被作为组合式API入口"><a href="#setup-选项实现组合式API；组件创建前，props被解析后，setup就会被作为组合式API入口" class="headerlink" title="setup() 选项实现组合式API；组件创建前，props被解析后，setup就会被作为组合式API入口"></a><code>setup()</code> 选项实现组合式API；组件创建前，<code>props</code>被解析后，<code>setup</code>就会被作为组合式API<strong>入口</strong></h4><ul>
<li><p>注意一下几点：</p>
<ol>
<li>由于进入<code>setup()</code>的时候，组件还未被创建，所以不能通过<code>this</code>获取<code>data</code>、<code>computed</code>、<code>methods</code>、<code>refs</code>的property</li>
<li><code>setup()</code>是一个接收<code>props</code>和<code>context</code>的函数</li>
<li><code>setup()</code>返回的内容，会暴露给<strong>组件的其他部分（计算属性、方法、生命周期钩子等待）</strong>和<strong>组件的模板</strong></li>
</ol>
</li>
<li><p><code>props</code>,是<code>setup()</code>的第一个参数</p>
<ol>
<li>props的是响应式的，有新值，就会被更新</li>
<li>因为props是响应式的，因此不能被<code>ES6解构</code></li>
<li>如果需要对props进行结构，需要引入并使用<code>toRefs(props)</code></li>
</ol>
</li>
<li><p><code>context</code>,是<code>setup()</code>的第二个参数（包含<code>attrs</code> <code>slots</code> <code>emits</code> <code>expose</code>）</p>
<ol>
<li><code>context</code>是一个普通的JavaScript对象，里面包含：<ul>
<li>attrs</li>
<li>slots</li>
<li>emit</li>
<li>expose（后面会分析）</li>
</ul>
</li>
<li><code>context</code>是一个对象，所以可以解构</li>
<li>建议对<code>context</code>进行解构，方便以<code>attrs.x</code>、<code>slots.x</code>的形式引用property.</li>
<li>不能对解构的<code>attrs</code>等，再进行解构。</li>
</ol>
</li>
<li><p>在模板中，使用<code>setup()</code>中返回的值，不需要<code>.value</code>,因为在模板中访问时是<code>被自动浅解包</code>的</p>
</li>
<li><p><code>setup()</code>的返回内容，可以是内部定义的值、方法。还可以是渲染函数。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ref , h &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params">props,context</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> count =ref(<span class="number">0</span>);</span><br><span class="line">    <span class="keyword">const</span> increment = <span class="function">()=&gt;</span> ++count.value;</span><br><span class="line">    <span class="keyword">return</span> <span class="function">()=&gt;</span> &#123;</span><br><span class="line">      h(<span class="string">&#x27;div&#x27;</span>,count.value); </span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>问题来了，要是返回的是一个<code>渲染函数</code>，里面的函数怎样通过模板暴露给父组件？答案就是：<code>expose</code>函数</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ref , expose , h &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params">props,context</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> count =ref(<span class="number">0</span>);</span><br><span class="line">    <span class="keyword">const</span> increment = <span class="function">()=&gt;</span> ++count.value;</span><br><span class="line">    expose(&#123;</span><br><span class="line">      increment,  <span class="comment">// 这个 increment 方法现在将可以通过父组件的模板 ref 访问。</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> <span class="function">()=&gt;</span> &#123;</span><br><span class="line">      h(<span class="string">&#x27;div&#x27;</span>,count.value); </span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="ref-和reactive-都可以将setup-中的数据创建一个响应式引用。变量的传递变成了传递引用"><a href="#ref-和reactive-都可以将setup-中的数据创建一个响应式引用。变量的传递变成了传递引用" class="headerlink" title="ref()和reactive() 都可以将setup()中的数据创建一个响应式引用。变量的传递变成了传递引用"></a><code>ref()</code>和<code>reactive()</code> 都可以将<code>setup()</code>中的数据创建一个响应式引用。变量的传递变成了传递引用</h4><ul>
<li><code>ref()</code> 推荐定义基本数据类型</li>
<li><code>reactive()</code> 推荐定义复杂的数据类型</li>
</ul>
<h4 id="setup-内生命周期钩子"><a href="#setup-内生命周期钩子" class="headerlink" title="setup() 内生命周期钩子"></a><code>setup()</code> 内生命周期钩子</h4><blockquote>
<p>相较于选项里面的钩子,<code>setup()</code>中只需要加一个on就可以</p>
</blockquote>
<blockquote>
<p>本来应该还有<code>beforeCreate</code> <code>created</code>，由于<code>setup()</code>正处于这两个周期中，所以在<code>setup()</code>中被取消了。而其中的逻辑代码可以写在<code>setup()</code>中。</p>
</blockquote>
<ul>
<li>onBeforeMount</li>
<li>onMounted</li>
<li>onBeforeUpdate</li>
<li>onUpdated</li>
<li>onBeforeUnmount</li>
<li>onUnmounted</li>
<li>onErrorCaptured</li>
<li>onRenderTracked</li>
<li>onRenderTriggered</li>
<li>onActivated</li>
<li>onDeactivated<blockquote>
<p>这些函数接收一个<code>回调函数 callFunction</code>,当钩子被组件调用的时候，该回调函数会被执行。</p>
</blockquote>
</li>
</ul>
<h4 id="watch响应式更改"><a href="#watch响应式更改" class="headerlink" title="watch响应式更改"></a><code>watch</code>响应式更改</h4><ul>
<li>注意以下几点：<ol>
<li><code>watch</code>需全局导入</li>
<li><code>watch</code>接收三个参数<ul>
<li>需要侦听的<strong>响应式引用</strong>或getter函数</li>
<li>回调函数</li>
<li>可选的配置选项【deep:true】</li>
</ul>
</li>
<li>侦听单个数据源<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ref , watch &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span><br><span class="line">  <span class="function"><span class="title">setup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> count = ref(<span class="number">0</span>);</span><br><span class="line">    watch(count,<span class="function">(<span class="params">newValue,oldValue</span>)=&gt;</span>&#123;</span><br><span class="line">      <span class="comment">// 进行操作</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>侦听多个数据源【使用数组】<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> firstName = ref(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> lastName = ref(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line"></span><br><span class="line">watch([firstName, lastName], <span class="function">(<span class="params">newValues, prevValues</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(newValues, prevValues)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 单个修改</span></span><br><span class="line">firstName.value = <span class="string">&#x27;John&#x27;</span> <span class="comment">// logs: [&quot;John&quot;, &quot;&quot;] [&quot;&quot;, &quot;&quot;]</span></span><br><span class="line">lastName.value = <span class="string">&#x27;Smith&#x27;</span> <span class="comment">// logs: [&quot;John&quot;, &quot;Smith&quot;] [&quot;John&quot;, &quot;&quot;]</span></span><br><span class="line"><span class="comment">// 一次性多个修改</span></span><br><span class="line"><span class="keyword">const</span> changeValues = <span class="function">()=&gt;</span>&#123;</span><br><span class="line">  firstName.value = <span class="string">&#x27;John&#x27;</span></span><br><span class="line">  lastName.value = <span class="string">&#x27;Smith&#x27;</span> </span><br><span class="line">  <span class="comment">// 打印 [&quot;John&quot;, &quot;Smith&quot;] [&quot;&quot;, &quot;&quot;]</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>侦听数组、对象<blockquote>
<p>由于数据是响应的，要求有一个由值构成的副本</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> numbers = reactive([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]);</span><br><span class="line">watch(</span><br><span class="line">  <span class="function">()=&gt;</span>[...numbers], <span class="comment">//getter函数</span></span><br><span class="line">  <span class="function">(<span class="params">numbers,prevNumbers</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(numbers,prevNumbers);</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line">numbers.push(<span class="number">5</span>);  <span class="comment">//logs: [1,2,3,4,5] [1,2,3,4]</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>对于深度嵌套对象或数组，需要添加<code>deep:true</code>的选项</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> state = reactive(&#123; </span><br><span class="line">  <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">  <span class="attr">attributes</span>: &#123; </span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">watch(  <span class="comment">// 无效，没有deep不能修改深度嵌套的对象</span></span><br><span class="line">  <span class="function">() =&gt;</span> state,  <span class="comment">//getter函数</span></span><br><span class="line">  <span class="function">(<span class="params">state, prevState</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;not deep&#x27;</span>, state.attributes.name, prevState.attributes.name)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">watch(  <span class="comment">// 有效</span></span><br><span class="line">  <span class="function">() =&gt;</span> state,  <span class="comment">//getter函数</span></span><br><span class="line">  <span class="function">(<span class="params">state, prevState</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;deep&#x27;</span>, state.attributes.name, prevState.attributes.name)</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123; <span class="attr">deep</span>: <span class="literal">true</span> &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">state.attributes.name = <span class="string">&#x27;Alex&#x27;</span> <span class="comment">// 日志: &quot;deep&quot; &quot;Alex&quot; &quot;&quot;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>为了完全深度侦听深度嵌套的对象或数组，需要使用<strong>外部工具</strong>进行深度拷贝</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> _ <span class="keyword">from</span> <span class="string">&#x27;lodash&#x27;</span></span><br><span class="line"><span class="keyword">const</span> state = reactive(&#123;</span><br><span class="line">  <span class="attr">id</span>:<span class="number">1</span>,</span><br><span class="line">  <span class="attr">attributes</span>:&#123;</span><br><span class="line">    <span class="attr">name</span>:<span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line">watch(</span><br><span class="line">  <span class="function">() =&gt;</span> _.cloneDeep(state),   <span class="comment">//深度拷贝</span></span><br><span class="line">  <span class="function">(<span class="params">state,prevState</span>) =&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(state.attributes.name, prevState.attributes.name);</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line">state.attributes.name = <span class="string">&#x27;Alex&#x27;</span> <span class="comment">// 日志: &quot;Alex&quot; &quot;&quot; </span></span><br></pre></td></tr></table></figure></li>
</ol>
</li>
</ul>
<h4 id="computed函数"><a href="#computed函数" class="headerlink" title="computed函数"></a><code>computed</code>函数</h4><blockquote>
<p>允许在组件外部创建计算属性。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ref , computed &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> count = ref(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">const</span> twiceTheCount = computed( <span class="function">()=&gt;</span> count.value * <span class="number">2</span> );</span><br><span class="line">coute.value++;</span><br><span class="line"><span class="built_in">console</span>.log(count.value); <span class="comment">//1</span></span><br><span class="line"><span class="built_in">console</span>.log(twiceTheCount.value); <span class="comment">//2</span></span><br></pre></td></tr></table></figure>

<h4 id="组合API的总结"><a href="#组合API的总结" class="headerlink" title="组合API的总结"></a>组合API的总结</h4><blockquote>
<p>个人理解，其实就是把组件内的<code>选项</code>化为<code>函数</code>，将然后将一些<code>通用的</code>、<code>共享的</code>一些数据、方法提取出来。实现代码的复用、分离。<br>通过一个类似于钩子函数的<code>setup()</code>进行整合，抛出。</p>
</blockquote>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>Copyright： </strong>
          
          Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
          
        </li>
      </ul>
    </div>
    
    <footer class="article-footer">
       
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>

<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://example.com/2022/01/19/Vue%E5%AD%A6%E4%B9%A0/Vue3/" alt="微信分享二维码">
    </div>
</div>

<div id="share-mask"></div>  
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Vue-js/" rel="tag">Vue.js</a></li></ul>

    </footer>
  </div>

   
  <nav class="article-nav">
    
      <a href="/2022/01/19/%E6%97%A5%E5%B8%B8/%E8%B5%B7%E6%BA%90/" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
          
            起源
          
        </div>
      </a>
    
    
      <a href="/2022/01/19/Vue%E5%AD%A6%E4%B9%A0/axios/" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">axios笔记</div>
      </a>
    
  </nav>

   
<!-- valine评论 -->
<div id="vcomments-box">
  <div id="vcomments"></div>
</div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js"></script>
<script>
  new Valine({
    el: "#vcomments",
    app_id: "jeb2pvxjdeJQOj5OG3AUavGv-gzGzoHsz",
    app_key: "6YlB9tQJTstHMM8GOwFu4uyY",
    path: window.location.pathname,
    avatar: "monsterid",
    placeholder: "给我的文章加点评论吧~",
    recordIP: true,
  });
  const infoEle = document.querySelector("#vcomments .info");
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
    infoEle.childNodes.forEach(function (item) {
      item.parentNode.removeChild(item);
    });
  }
</script>
<style>
  #vcomments-box {
    padding: 5px 30px;
  }

  @media screen and (max-width: 800px) {
    #vcomments-box {
      padding: 5px 0px;
    }
  }

  #vcomments-box #vcomments {
    background-color: #fff;
  }

  .v .vlist .vcard .vh {
    padding-right: 20px;
  }

  .v .vlist .vcard {
    padding-left: 10px;
  }
</style>

 
   
     
</article>

</section>
      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2022
        <i class="ri-heart-fill heart_icon"></i> 子与子乘
      </li>
    </ul>
    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>Visitors:<span id="busuanzi_value_site_uv"></span></span>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>Views:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
      </li>
    </ul>
  </div>
</footer>    
    </main>
    <div class="float_btns">
      <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

    </div>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="欢迎"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/friends">友链</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i></p>
  <div class="reward-box">
    
    
  </div>
</div>
    
<script src="/js/jquery-3.6.0.min.js"></script>
 
<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->
 
<script src="/js/tocbot.min.js"></script>

<script>
  tocbot.init({
    tocSelector: ".tocbot",
    contentSelector: ".article-entry",
    headingSelector: "h1, h2, h3, h4, h5, h6",
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: "main",
    positionFixedSelector: ".tocbot",
    positionFixedClass: "is-position-fixed",
    fixedSidebarOffset: "auto",
  });
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css"
/>
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->
 <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script> 
<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->
 
<script src="/js/busuanzi-2.3.pure.min.js"></script>
 
<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->

<!-- CodeCopy -->
 
<link rel="stylesheet" href="/css/clipboard.css">
 <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>
 
<!-- CanvasBackground -->

<script>
  if (window.mermaid) {
    mermaid.initialize({ theme: "forest" });
  }
</script>


    
    

  </div>
</body>

</html>